from collections import Counter
from collections import deque
import datetime
import math
import numpy as np
import cv2


class direction():
	def __init__(self ):
		self.memory = {}
		self.up_count = 0
		self.down_count = 0
		# self.line = [(0, int(0.5 * img.shape[0])), (int(img.shape[1]), int(0.5 * img.shape[0]))]
		self.already_counted = deque(maxlen=50)	 # 存放已经计数的追踪目标
		self.total_counter = 0  # 出入通过的总人数

	# 线与线的碰撞检测：叉乘的方法判断两条线是否相交
	# 计算叉乘符号
	def ccw(self, A, B, C):

		return (C[1]-A[1]) * (B[0]-A[0]) > (B[1]-A[1]) * (C[0]-A[0])

	# 检测AB和CD两条直线是否相交
	def is_intersection(self, A, B, C, D):
		print('is_intersection', self.ccw(A, C, D), self.ccw(B, C, D), self.ccw(A, B, C), self.ccw(A, B, D))
		return self.ccw(A, C, D) != self.ccw(B, C, D) and self.ccw(A, B, C) != self.ccw(A, B, D)

	# 将坐标格式化，转换为中心点坐标
	def tlbr_midpoint(self, box):
		'''
		Finds midpoint of a box in tlbr format.
		(top left, bottom right)
		'''
		minX, minY, maxX, maxY = box
		t = 1 / 2 	# 中心坐标系数，可以控制中心点的纵坐标
		midpoint = (int((minX + maxX) / 2), int((minY + maxY) * t))  # minus y coordinates to get proper xy format
		return midpoint

	# 计算追踪目标中心点与划线所围成的区域面积
	def direct(self, midpoint, line):

		direct_x = ((midpoint[0] - line[0][0])*(line[1][1] - line[0][1]))
		direct_y = ((midpoint[1] - line[0][1])*(line[1][0] - line[0][0]))
		direct = direct_x - direct_y
		return direct

	def line_direction(self, img, bbox, identities=None):

		#  划线的信息
		# line = [(0, int(0.5 * img.shape[0])), (int(img.shape[1]), int(0.5 * img.shape[0]))]
		line = [(int(0.5 * img.shape[1]), 0), (int(0.5 * img.shape[1]), int(img.shape[0]))]
		flag = False  # 用于判断人过线时的标记

		for i, box in enumerate(bbox):
			# x1, y1, x2, y2 = [int(i) for i in box]
			# 	当前跟踪目标的中心坐标
			midpoint = self.tlbr_midpoint(box)
			id = int(identities[i]) if identities is not None else 0

			# 先判断追踪的id号是否已经在 memory字典当中，若不在，创建一个队列
			if id not in self.memory:
				self.memory[id] = deque(maxlen=2)
			# 在字典中添加当前追踪节点的中心点坐标，添加是放在队尾,若超出长度，则会让队尾的出队
			self.memory[id].append(midpoint)
			#  取出对应id上一次的中心点坐标信息
			previous_midpoint = self.memory[id][0]
			# 作图，画出前后中心点的轨迹图
			# print('midpoint, previous_midpoint:', midpoint, previous_midpoint,line[0], line[1])
			cv2.line(img, midpoint, previous_midpoint, (0, 255, 0), 2)

			# 计算追踪目标出入方向
			# and id not in self.already_counted
			if self.is_intersection(midpoint, previous_midpoint, line[0], line[1]):
				self.total_counter += 1

				flag = True

				# Set already counted for ID to true.
				self.already_counted.append(id)

				direction = self.direct(midpoint, line)
				if direction > 0:
					self.up_count += 1
				if direction < 0:
					self.down_count += 1

			# Delete memory of old tracks.
			# This needs to be larger than the number of tracked objects in the frame.
			if len(self.memory) > 50:
				del self.memory[list(self.memory)[0]]

			# Draw total count.
			# cv2.putText(img, "Total: {} ({} up, {} down)".format(str(self.total_counter), str(self.up_count),
			# 													 str(self.down_count)),
			# 			(int(0.05 * img.shape[1]), int(0.1 * img.shape[0])), 0,
			# 			1.5e-3 * img.shape[0], (0, 255, 255), 2)

		return img, self.total_counter, self.up_count, self.down_count, flag

	# 作图，画出图中的区域框和检测流量的数量
	def draw_line(self, img, total_counter, up_count, down_count, flag):

		# line = [(0, int(0.5 * img.shape[0])), (int(img.shape[1]), int(0.5 * img.shape[0]))]
		line = [(int(0.5 * img.shape[1]), 0), (int(0.5 * img.shape[1]), int(img.shape[0]))]

		# draw yellow line  在图中画出检测线  flag 区分是否跨线标志， 跨线画红线
		if flag:
			cv2.line(img, line[0], line[1], (0, 0, 255), 2)
		else:
			cv2.line(img, line[0], line[1], (0, 255, 255), 2)

		# Draw total count.
		cv2.putText(img, "Total: {} ({} up, {} down)".format(str(total_counter), str(up_count), str(down_count)),
					(int(0.05 * img.shape[1]), int(0.1 * img.shape[0])), 0,
					1.5e-3 * img.shape[0], (0, 255, 255), 2)

		return img


	# def line_direction(self, img, bbox, identities=None):
	#
	# 	#  划线的信息
	# 	line = [(0, int(0.5 * img.shape[0])), (int(img.shape[1]), int(0.5 * img.shape[0]))]
	#
	# 	# draw yellow line  在图中画出检测线
	# 	cv2.line(img, line[0], line[1], (0, 255, 255), 2)
	# 	for i, box in enumerate(bbox):
	# 		x1, y1, x2, y2 = [int(i) for i in box]
	# 		# 	当前跟踪目标的中心坐标
	# 		midpoint = self.tlbr_midpoint(box)
	# 		id = int(identities[i]) if identities is not None else 0
	#
	# 		# 先判断追踪的id号是否已经在 memory字典当中，若不在，创建一个队列
	# 		if id not in self.memory:
	# 			self.memory[id] = deque(maxlen=2)
	# 		# 在字典中添加当前追踪节点的中心点坐标，添加是放在队尾,若超出长度，则会让队尾的出队
	# 		self.memory[id].append(midpoint)
	# 		#  取出对应id上一次的中心点坐标信息
	# 		previous_midpoint = self.memory[id][0]
	# 		# 作图，画出前后中心点的轨迹图
	# 		cv2.line(img, midpoint, previous_midpoint, (0, 255, 0), 2)
	#
	# 		# 计算追踪目标出入方向
	# 		if self.is_intersection(midpoint, previous_midpoint, line[0],
	# 								line[1]) and id not in self.already_counted:
	# 			self.total_counter += 1
	#
	# 			# 画上红线
	# 			cv2.line(img, line[0], line[1], (0, 0, 255), 2)
	#
	# 			# Set already counted for ID to true.
	# 			self.already_counted.append(id)
	#
	# 			direction = self.direct(midpoint, line)
	# 			if direction > 0:
	# 				self.up_count += 1
	# 			if direction < 0:
	# 				self.down_count += 1
	#
	# 		# Delete memory of old tracks.
	# 		# This needs to be larger than the number of tracked objects in the frame.
	# 		if len(self.memory) > 50:
	# 			del self.memory[list(self.memory)[0]]
	#
	# 		# Draw total count.
	# 		cv2.putText(img, "Total: {} ({} up, {} down)".format(str(self.total_counter), str(self.up_count),
	# 															 str(self.down_count)),
	# 					(int(0.05 * img.shape[1]), int(0.1 * img.shape[0])), 0,
	# 					1.5e-3 * img.shape[0], (0, 255, 255), 2)
	#
	# 		return img

	# def line_direction(self, img, bbox, identities=None):
	#
	# 	#  划线的信息
	# 	line = [(0, int(0.5 * img.shape[0])), (int(img.shape[1]), int(0.5 * img.shape[0]))]
	#
	# 	memory = {}
	# 	up_count = 0
	# 	down_count = 0
	# 	already_counted = deque(maxlen=50)	 # 存放已经计数的追踪目标
	# 	total_counter = 0  # 出入通过的总人数
	#
	# 	for i, box in enumerate(bbox):
	# 		x1, y1, x2, y2 = [int(i) for i in box]
	# 		# 	当前跟踪目标的中心坐标
	# 		midpoint = self.tlbr_midpoint(box)
	# 		id = int(identities[i]) if identities is not None else 0
	#
	# 		# 先判断追踪的id号是否已经在 memory字典当中，若不在，创建一个队列
	# 		if id not in memory:
	# 			memory[id] = deque(maxlen=2)
	# 		# 在字典中添加当前追踪节点的中心点坐标，添加是放在队尾,若超出长度，则会让队尾的出队
	# 		memory[id].append(midpoint)
	# 		#  取出对应id上一次的中心点坐标信息
	# 		previous_midpoint = memory[id][0]
	# 		# 作图，画出前后中心点的轨迹图
	# 		print('midpoint, previous_midpoint:', midpoint, previous_midpoint, i)
	# 		cv2.line(img, midpoint, previous_midpoint, (0, 255, 0), 2)
	#
	# 		# 计算追踪目标出入方向
	# 		# and id not in already_counted
	# 		if self.is_intersection(midpoint, previous_midpoint, line[0], line[1]):
	# 			total_counter += 1
	#
	# 			# 画上红线
	# 			cv2.line(img, line[0], line[1], (0, 0, 255), 2)
	#
	# 			# Set already counted for ID to true.
	# 			already_counted.append(id)
	#
	# 			direction = self.direct(midpoint, line)
	# 			if direction > 0:
	# 				up_count += 1
	# 			if direction < 0:
	# 				down_count += 1
	#
	# 		# Delete memory of old tracks.
	# 		# This needs to be larger than the number of tracked objects in the frame.
	# 		if len(memory) > 50:
	# 			del memory[list(memory)[0]]
	#
	# 		return img, total_counter, up_count, down_count





